﻿using Sttplay.Transmission.TCP;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;

namespace transmission
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>

    public enum TransmissionType
    {
        None,
        TcpServer,
        TcpClient,
        Udp,
        SerialPort
    }


    public partial class MainWindow : Window
    {
        private TransmissionType selectType = TransmissionType.None;
        private DispatcherTimer timer = new DispatcherTimer();
        private List<TCPServerContext> tcpServerList = new List<TCPServerContext>();
        private List<TCPClientContext> tcpClientList = new List<TCPClientContext>();
        private List<UDPContext> udpList = new List<UDPContext>();
        private List<SerialPortContext> serialPortList = new List<SerialPortContext>();
        public static MainWindow Instance;
        public Context context;
        public string topSelect;
        public TreeViewItem selectItem;
        public MainWindow()
        {
            Instance = this;
            InitializeComponent();
            createBtn.IsEnabled = false;
            deleteBtn.IsEnabled = false;
            timer.Interval = new TimeSpan(0, 0, 0, 0, 16);
            timer.Tick += Tick;
            timer.Start();
            EnableAll(TransmissionType.None, false);
        }

        private void Tick(object sender, EventArgs e)
        {
            foreach (var item in tcpServerList)
                item.Update();
            foreach (var item in tcpClientList)
                item.Update();
            foreach (var item in udpList)
                item.Update();
            foreach (var item in serialPortList)
                item.Update();
        }

        private void EnableAll(TransmissionType type, bool enable)
        {
            if (type == TransmissionType.TcpServer)
            {
                stateGroupBox.Visibility = enable ? Visibility.Visible : Visibility.Hidden;
                recvGroupBox.Visibility = Visibility.Hidden;
                sendGroupBox.Visibility = Visibility.Hidden;
                bottomGrid.Visibility = Visibility.Hidden;
            }
            else
            {
                stateGroupBox.Visibility = enable ? Visibility.Visible : Visibility.Hidden;
                recvGroupBox.Visibility = enable ? Visibility.Visible : Visibility.Hidden;
                sendGroupBox.Visibility = enable ? Visibility.Visible : Visibility.Hidden;
                bottomGrid.Visibility = enable ? Visibility.Visible : Visibility.Hidden;
            }
        }

        private void OnCreateBtnClicked(object sender, RoutedEventArgs e)
        {
            if (selectType == TransmissionType.TcpServer)
            {
                TCPServerCreate create = new TCPServerCreate();
                if (create.ShowDialog() != true)
                    return;
                foreach (var item in tcpServerList)
                {
                    if (item.GetPort() == create.GetPort())
                    {
                        MessageBox.Show(string.Format("端口{0}已被使用", item.GetPort()), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }
                TCPServerContext context = new TCPServerContext(create.GetIP(), create.GetPort(), create.GetIsPacket());
                bool startFailed = false;
                if (!context.InitializeServer())
                {
                    startFailed = true;
                    MessageBox.Show(string.Format("初始化服务器{0}:{1}失败", create.GetIP(), create.GetPort()), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
                TreeViewItem vi = context.GetTreeViewItem();
                tcpServerList.Add(context);
                treeTcpServer.Items.Add(vi);
                vi.PreviewMouseDown += OnTreeBtnClicked;
                OnTreeBtnClicked(vi, null);
                stateLed.Background = startFailed ? Brushes.Gray : new SolidColorBrush(Color.FromRgb(20, 255, 0));
            }
            else if (selectType == TransmissionType.TcpClient)
            {
                TCPClientCreate create = new TCPClientCreate();
                if (create.ShowDialog() != true)
                    return;
                TCPClient client = new TCPClient(create.GetIsPacket());
                TCPClientContext context = new TCPClientContext(client, create.GetIP(), create.GetPort(), false);
                TreeViewItem vi = context.GetTreeViewItem();
                tcpClientList.Add(context);
                treeTcpClient.Items.Add(vi);
                vi.PreviewMouseDown += OnTreeBtnClicked;
                OnTreeBtnClicked(vi, null);
                stateLed.Background = Brushes.Gray;
            }
            else if (selectType == TransmissionType.Udp)
            {
                UDPCreate create = new UDPCreate();
                if (create.ShowDialog() != true)
                    return;

                UDPContext context = new UDPContext();
                if (create.udpGrid.Visibility == Visibility.Visible)
                {
                    if (!context.InitUdp(create.GetRemoteIP(), create.GetRemotePort(), create.GetLocalIP(), create.GetLocalPort(), create.GetIsReliable()))
                    {
                        MessageBox.Show(string.Format("初始化UDP服务器{0}:{1}失败", create.GetLocalIP(), create.GetLocalPort()), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }
                else
                {
                    if (!context.InitUdpGroup(create.GetGroupIP(), create.GetGroupPort(), create.GetLocalIP()))
                    {
                        MessageBox.Show(string.Format("初始化UDP服务器{0}:{1}失败", create.GetLocalIP(), create.GetGroupPort()), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }
                TreeViewItem vi = context.GetTreeViewItem();
                udpList.Add(context);
                treeUDP.Items.Add(vi);
                vi.PreviewMouseDown += OnTreeBtnClicked;
                OnTreeBtnClicked(vi, null);
            }
            else if (selectType == TransmissionType.SerialPort)
            {
                SerialPortCreate create = new SerialPortCreate();
                if (create.ShowDialog() != true)
                    return;
                foreach (var item in serialPortList)
                {
                    if (item.COM == create.GetCOM() && item.buardRate == create.GetBuardrate())
                    {
                        MessageBox.Show(string.Format("串口{0}已被使用", item.COM), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                        return;
                    }
                }
                SerialPortContext context = new SerialPortContext();
                context.COM = create.GetCOM();
                context.buardRate = create.GetBuardrate();
                context.parity = create.GetParity();
                context.dataBits = create.GetDataBits();
                context.stopBits = create.GetStopBits();
                context.DTR = create.isDTR.IsChecked == true;
                context.RTS = create.isRTS.IsChecked == true;
                context.Init();
                if (!context.Open())
                {
                    MessageBox.Show(string.Format("串口{0}已被使用，请先停止正在使用的串口", context.COM), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                }
                TreeViewItem vi = context.GetTreeViewItem();
                serialPortList.Add(context);
                treeSerialPort.Items.Add(vi);
                vi.PreviewMouseDown += OnTreeBtnClicked;
                OnTreeBtnClicked(vi, null);
            }
        }

        private void OnDeleteBtnClicked(object sender, RoutedEventArgs e)
        {
            TreeViewItem item = treeView.SelectedItem as TreeViewItem;
            StackPanelEx panel = item.Header as StackPanelEx;
            if (panel.type == TransmissionType.TcpServer)
            {
                TCPServerContext context = panel.user as TCPServerContext;
                context.Release();
                item.PreviewMouseDown += OnTreeBtnClicked;
                treeTcpServer.Items.Remove(item);
                tcpServerList.Remove(context);
                treeTcpServer.IsSelected = true;
                OnTreeBtnClicked(treeTcpServer, null);
            }
            else if (panel.type == TransmissionType.TcpClient)
            {
                TreeViewItem parent = item.Parent as TreeViewItem;
                StackPanelEx parentPanel = parent.Header as StackPanelEx;
                if (parentPanel == null)
                {
                    TCPClientContext context = panel.user as TCPClientContext;
                    context.OnDisconnected();
                    treeTcpClient.Items.Remove(context.GetTreeViewItem());
                    tcpClientList.Remove(context);
                }
                else
                {
                    TCPServerContext context = parentPanel.user as TCPServerContext;
                    context.OnManualClose(panel.user as TCPClientContext);
                }
                OnTreeBtnClicked(parent, null);
            }
            else if (panel.type == TransmissionType.Udp)
            {
                TreeViewItem parent = item.Parent as TreeViewItem;
                UDPContext context = panel.user as UDPContext;
                context.Terminate();
                treeUDP.Items.Remove(context.GetTreeViewItem());
                udpList.Remove(context);
                OnTreeBtnClicked(parent, null);
            }
            else if (panel.type == TransmissionType.SerialPort)
            {
                TreeViewItem parent = item.Parent as TreeViewItem;
                SerialPortContext context = panel.user as SerialPortContext;
                context.Close();
                treeSerialPort.Items.Remove(context.GetTreeViewItem());
                serialPortList.Remove(context);
                OnTreeBtnClicked(parent, null);
            }
        }

        private void GetTopSelect(TreeViewItem item)
        {
            TreeViewItem parent = item;
            do
            {
                topSelect = parent.Header as string;
                parent = parent.Parent as TreeViewItem;
            }
            while (parent != null);
        }
        public void OnTreeBtnClicked(object sender, MouseButtonEventArgs e)
        {
            TreeViewItem item = selectItem = sender as TreeViewItem;
            TreeViewItem parent = item.Parent as TreeViewItem;
            GetTopSelect(item);
            if (parent == null)
            {
                string header = item.Header as string;
                if (header == "TCP Server")
                    selectType = TransmissionType.TcpServer;
                else if (header == "TCP Client")
                    selectType = TransmissionType.TcpClient;
                else if (header == "UDP")
                    selectType = TransmissionType.Udp;
                else if (header == "Serial Port")
                    selectType = TransmissionType.SerialPort;
                createBtn.IsEnabled = true;
                deleteBtn.IsEnabled = false;
                EnableAll(TransmissionType.None, false);
                this.context = null;
            }
            else
            {
                selectType = TransmissionType.None;
                createBtn.IsEnabled = false;
                deleteBtn.IsEnabled = true;
                StackPanelEx panel = item.Header as StackPanelEx;
                if (panel != null)
                {
                    EnableAll(panel.type, true);
                    if (panel.type == TransmissionType.TcpServer)
                    {
                        openBtn.Content = "启用";
                        closeBtn.Content = "关闭";
                        stateLed.Visibility = Visibility.Visible;
                        openBtn.Visibility = Visibility.Visible;
                        closeBtn.Visibility = Visibility.Visible;
                        TCPServerContext context = panel.user as TCPServerContext;
                        openBtn.IsEnabled = !context.IsRun;
                        closeBtn.IsEnabled = context.IsRun;
                        stateLed.Background = context.IsRun ? new SolidColorBrush(Color.FromRgb(20, 255, 0)) : Brushes.Gray;
                        endPointGrid.Visibility = Visibility.Hidden;
                        groupcastGrid.Visibility = Visibility.Hidden;
                        serialPortGrid.Visibility = Visibility.Hidden;
                    }
                    else if (panel.type == TransmissionType.TcpClient)
                    {
                        endPointGrid.Visibility = Visibility.Visible;
                        groupcastGrid.Visibility = Visibility.Hidden;
                        serialPortGrid.Visibility = Visibility.Hidden;
                        TCPClientContext context = panel.user as TCPClientContext;
                        this.context = context;
                        StackPanelEx parentPanel = parent.Header as StackPanelEx;
                        if (parentPanel == null)
                        {
                            stateLed.Visibility = Visibility.Visible;
                            openBtn.Visibility = Visibility.Visible;
                            closeBtn.Visibility = Visibility.Visible;
                            openBtn.Content = "连接";
                            closeBtn.Content = "断开";
                            openBtn.IsEnabled = context.StateColor == Brushes.Gray;
                            closeBtn.IsEnabled = context.StateColor != Brushes.Gray;
                            stateLed.Background = context.StateColor;
                            remoteIP.Content = context.GetRemoteIP();
                            remotePort.Content = context.GetRemotePort();
                            localPort.Content = context.GetLocalPort();
                        }
                        else
                        {
                            stateLed.Background = new SolidColorBrush(Color.FromRgb(20, 255, 0));
                            stateLed.Visibility = Visibility.Visible;
                            openBtn.Visibility = Visibility.Hidden;
                            closeBtn.Content = "断开";
                            remoteIP.Content = context.GetRemoteIP();
                            remotePort.Content = context.GetRemotePort();
                            localPort.Content = context.GetLocalPort();
                        }
                        sendText.Text = this.context.SendText;
                        UpdateContextText(this.context);
                        tipBar.Content = this.context.LogText;
                        hexCheckBox.IsChecked = this.context.HexMode;
                    }
                    else if (panel.type == TransmissionType.Udp)
                    {
                        UDPContext context = panel.user as UDPContext;
                        endPointGrid.Visibility = context.isGroupcastMode ? Visibility.Hidden : Visibility.Visible;
                        groupcastGrid.Visibility = context.isGroupcastMode ? Visibility.Visible : Visibility.Hidden;
                        serialPortGrid.Visibility = Visibility.Hidden;
                        this.context = context;
                        stateLed.Visibility = Visibility.Visible;
                        openBtn.Visibility = Visibility.Hidden;
                        closeBtn.Visibility = Visibility.Hidden;
                        remoteIP.Content = context.remoteIP;
                        remotePort.Content = context.remotePort;
                        localPort.Content = context.localPort;
                        groupIP.Content = context.groupIP;
                        groupPort.Content = context.groupPort;
                        stateLed.Background = new SolidColorBrush(Color.FromRgb(20, 255, 0));
                        sendText.Text = this.context.SendText;
                        UpdateContextText(this.context);
                        tipBar.Content = this.context.LogText;
                        hexCheckBox.IsChecked = this.context.HexMode;
                    }
                    else if (panel.type == TransmissionType.SerialPort)
                    {
                        SerialPortContext context = panel.user as SerialPortContext;
                        this.context = context;
                        endPointGrid.Visibility = Visibility.Hidden;
                        groupcastGrid.Visibility = Visibility.Hidden;
                        serialPortGrid.Visibility = Visibility.Visible;
                        stateLed.Visibility = Visibility.Visible;
                        openBtn.Visibility = Visibility.Visible;
                        closeBtn.Visibility = Visibility.Visible;
                        openBtn.Content = "打开";
                        closeBtn.Content = "关闭";
                        openBtn.IsEnabled = context.StateColor == Brushes.Gray;
                        closeBtn.IsEnabled = context.StateColor != Brushes.Gray;
                        stateLed.Background = context.StateColor;
                        com.Content = context.COM;
                        buardRate.Content = context.buardRate;
                        sendText.Text = this.context.SendText;
                        UpdateContextText(this.context);
                        tipBar.Content = this.context.LogText;
                        hexCheckBox.IsChecked = this.context.HexMode;
                    }
                }

            }
        }

        private void OnClosed(object sender, EventArgs e)
        {
            timer.Stop();
            foreach (var item in tcpServerList)
                item.Release();
            foreach (var item in tcpClientList)
                item.OnDisconnected();
        }

        private void OnInputTextChanged(object sender, TextChangedEventArgs e)
        {
            if (context == null) return;
            context.SendText = (e.Source as TextBox).Text;
        }

        private void OnSendBtnClicked(object sender, RoutedEventArgs e)
        {
            if (context == null) return;
            context.Send();
        }

        public void UpdateContextText(Context context)
        {
            if (context != this.context) return;
            recvText.Text = context.RecvText;
            recvText.ScrollToEnd();
        }

        private void OnCloseBtnClicked(object sender, RoutedEventArgs e)
        {
            TreeViewItem item = treeView.SelectedItem as TreeViewItem;
            if (item == null) return;
            StackPanelEx panel = item.Header as StackPanelEx;
            if (panel == null) return;
            if (panel.type == TransmissionType.TcpServer)
            {
                TCPServerContext context = panel.user as TCPServerContext;
                context.Release();
                stateLed.Background = Brushes.Gray;
                openBtn.IsEnabled = !context.IsRun;
                closeBtn.IsEnabled = context.IsRun;
            }
            if (panel.type == TransmissionType.TcpClient)
            {
                TreeViewItem parent = item.Parent as TreeViewItem;

                if (parent.Header as StackPanelEx == null)
                {
                    TCPClientContext context = panel.user as TCPClientContext;
                    context.OnDisconnected();
                }
                else
                    OnDeleteBtnClicked(sender, e);
            }
            if (panel.type == TransmissionType.SerialPort)
            {
                SerialPortContext context = panel.user as SerialPortContext;
                context.Close();
                stateLed.Background = context.StateColor;
                openBtn.IsEnabled = true;
                closeBtn.IsEnabled = false;
            }
        }

        private void OnOpenBtnClicked(object sender, RoutedEventArgs e)
        {
            TreeViewItem item = treeView.SelectedItem as TreeViewItem;
            if (item == null) return;
            StackPanelEx panel = item.Header as StackPanelEx;
            if (panel == null) return;
            if (panel.type == TransmissionType.TcpServer)
            {
                TCPServerContext context = panel.user as TCPServerContext;
                if (!context.InitializeServer())
                {
                    MessageBox.Show(string.Format("初始化服{0}:{1}务器失败", context.GetIP(), context.GetPort()), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                stateLed.Background = new SolidColorBrush(Color.FromRgb(20, 255, 0));
                openBtn.IsEnabled = !context.IsRun;
                closeBtn.IsEnabled = context.IsRun;
            }
            else if (panel.type == TransmissionType.TcpClient)
            {
                TCPClientContext context = panel.user as TCPClientContext;
                context.Connect();
                stateLed.Background = context.StateColor;
                openBtn.IsEnabled = false;
                closeBtn.IsEnabled = true;
            }
            else if (panel.type == TransmissionType.SerialPort)
            {
                SerialPortContext context = panel.user as SerialPortContext;
                if (!context.Open())
                {
                    MessageBox.Show(string.Format("串口{0}不存在或者已被使用", context.COM), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                stateLed.Background = context.StateColor;
                openBtn.IsEnabled = false;
                closeBtn.IsEnabled = true;
            }
        }

        public void OnClientConnectRet(TCPClientContext context, bool connectSuccess)
        {
            if (context != this.context) return;
            stateLed.Background = context.StateColor;
            openBtn.IsEnabled = !connectSuccess;
            closeBtn.IsEnabled = connectSuccess;
            remoteIP.Content = context.GetRemoteIP();
            remotePort.Content = context.GetRemotePort();
            localPort.Content = context.GetLocalPort();
        }

        private void OnCheckedChanged(object sender, RoutedEventArgs e)
        {
            if (this.context == null) return;
            this.context.HexMode = hexCheckBox.IsChecked == true;
        }

        public void OnTipbarLog(Context context, string msg)
        {
            if (context != this.context) return;
            tipBar.Content = msg;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.Key == Key.F1)
            {
                if (context == null) return;
                context.Trigger();
            }
        }
    }
}
